package com.ews.onlineexchange.model;

import java.util.ArrayList;
import java.util.Date;
import java.util.List;

import javax.persistence.CascadeType;
import javax.persistence.Entity;
import javax.persistence.FetchType;
import javax.persistence.JoinColumn;
import javax.persistence.ManyToOne;
import javax.persistence.NamedAttributeNode;
import javax.persistence.NamedEntityGraph;
import javax.persistence.OneToMany;
import javax.persistence.OneToOne;
import javax.persistence.PostLoad;
import javax.validation.constraints.NotNull;

import org.apache.lucene.analysis.cn.smart.SmartChineseAnalyzer;
import org.hibernate.annotations.DynamicInsert;
import org.hibernate.annotations.DynamicUpdate;
import org.hibernate.annotations.NotFound;
import org.hibernate.annotations.NotFoundAction;
import org.hibernate.search.annotations.Analyze;
import org.hibernate.search.annotations.Analyzer;
import org.hibernate.search.annotations.Boost;
import org.hibernate.search.annotations.Field;
import org.hibernate.search.annotations.Index;
import org.hibernate.search.annotations.Indexed;
import org.hibernate.search.annotations.IndexedEmbedded;
import org.hibernate.search.annotations.Store;
import org.hibernate.validator.constraints.Length;

import com.ews.onlineexchange.util.StringUtils;

/**
 * 文章Entity
 */
@Entity
@DynamicInsert
@DynamicUpdate
@Indexed(index = "all")
@Analyzer(impl = SmartChineseAnalyzer.class)
@Boost(1.0f)
@NamedEntityGraph( name = "Article-category-image-articleData", attributeNodes = {
		@NamedAttributeNode( value = "category" ),
		@NamedAttributeNode( value = "image" ),
		@NamedAttributeNode( value = "articleData" )
	} 
	
)
public class Article extends DataEntity implements FullTextResult {

	public static final String	DEFAULT_TEMPLATE	= "frontViewArticle";

	private static final long	serialVersionUID	= 1L;
	private Category 			category;									// 分类编号
	private String				title;										// 标题
	private String				link;										// 外部链接
	private String				color;										// 标题颜色（red：红色；green：绿色；blue：蓝色；yellow：黄色；orange：橙色）
	private Image				image;										// 文章图片
	private String				keywords;									// 关键字
	private String				description;								// 描述、摘要
	private Integer				weight				= 0;					// 权重，越大越靠前
	private Date				weightDate;									// 权重期限，超过期限，将weight设置为0
	private Long				hits				= 0L;					// 点击数
	private Date				editDate;									// 文章日期

	private String				publisher;									// 发布人

	private ArticleData			articleData = new ArticleData();			// 文章副表

	private String				stat				= "0";					// 0:未审核 1:已审核

	private Boolean				forceFormat			= Boolean.FALSE;
	
	private List<Attachment> 	attachment			= new ArrayList<Attachment>(); // 附件

	@ManyToOne
	@NotNull
	public Category getCategory() {
		return category;
	}

	public void setCategory(Category category) {
		this.category = category;
	}

	@Length(min = 1, max = 255)
	@Field(index = Index.YES, analyze = Analyze.YES, store = Store.NO)
	@Boost(1.0f)
	public String getTitle() {
		return title;
	}

	public void setTitle(String title) {
		this.title = title;
	}

	@Length(min = 0, max = 255)
	public String getLink() {
		return link;
	}

	public void setLink(String link) {
		this.link = link;
	}

	@Length(min = 0, max = 50)
	public String getColor() {
		return color;
	}

	public void setColor(String color) {
		this.color = color;
	}

	@Length(min = 0, max = 255)
	@Field(index = Index.YES, analyze = Analyze.YES, store = Store.NO)
	public String getKeywords() {
		return keywords;
	}

	public void setKeywords(String keywords) {
		this.keywords = keywords;
	}

	@Length(min = 0, max = 255)
	@Field(index = Index.YES, analyze = Analyze.YES, store = Store.NO)
	public String getDescription() {
		return description;
	}

	public void setDescription(String description) {
		this.description = description;
	}

	@NotNull
	public Integer getWeight() {
		return weight;
	}

	public void setWeight(Integer weight) {
		this.weight = weight;
	}

	public Date getWeightDate() {
		return weightDate;
	}

	public void setWeightDate(Date weightDate) {
		this.weightDate = weightDate;
	}

	public Long getHits() {
		return hits;
	}

	public void setHits(Long hits) {
		this.hits = hits;
	}

	@JoinColumn(unique = true)
	@OneToOne(fetch = FetchType.LAZY, cascade = CascadeType.ALL, optional = false)
	@NotFound(action = NotFoundAction.IGNORE)
	@IndexedEmbedded	
	public ArticleData getArticleData() {
		return articleData;
	}

	public void setArticleData(ArticleData articleData) {
		this.articleData = articleData;
	}

	@Field
	public String getStat() {
		return stat;
	}

	public void setStat(String stat) {
		this.stat = stat;
	}

	public Date getEditDate() {
		return editDate;
	}

	public void setEditDate(Date editDate) {
		this.editDate = editDate;
	}

	public String getPublisher() {
		return publisher;
	}

	public void setPublisher(String publisher) {
		this.publisher = publisher;
	}
	
	public Boolean getForceFormat() {
		return forceFormat;
	}

	public void setForceFormat(Boolean forceFormat) {
		this.forceFormat = forceFormat;
	}
	
	@OneToOne(cascade = CascadeType.ALL)
	public Image getImage() {
		return image;
	}

	public void setImage(Image image) {
		this.image = image;
	}

	@OneToMany(cascade = CascadeType.ALL)
	public List<Attachment> getAttachment() {
		return attachment;
	}

	public void setAttachment(List<Attachment> attachment) {
		this.attachment = attachment;
	}

	@Override
	public int hashCode() {
		final int prime = 31;
		int result = 1;		
		result = prime * result + ((color == null) ? 0 : color.hashCode());
		result = prime * result + ((description == null) ? 0 : description.hashCode());
		result = prime * result + ((editDate == null) ? 0 : editDate.hashCode());
		result = prime * result + ((forceFormat == null) ? 0 : forceFormat.hashCode());
		result = prime * result + ((hits == null) ? 0 : hits.hashCode());
		result = prime * result + ((image == null) ? 0 : image.hashCode());
		result = prime * result + ((keywords == null) ? 0 : keywords.hashCode());
		result = prime * result + ((link == null) ? 0 : link.hashCode());
		result = prime * result + ((publisher == null) ? 0 : publisher.hashCode());
		result = prime * result + ((stat == null) ? 0 : stat.hashCode());
		result = prime * result + ((title == null) ? 0 : title.hashCode());
		result = prime * result + ((weight == null) ? 0 : weight.hashCode());
		result = prime * result + ((weightDate == null) ? 0 : weightDate.hashCode());
		return result;
	}

	@Override
	public boolean equals(Object obj) {
		if (this == obj)
			return true;
		if (obj == null)
			return false;
		if (getClass() != obj.getClass())
			return false;
		Article other = (Article) obj;		
		if (color == null) {
			if (other.color != null)
				return false;
		} else if (!color.equals(other.color))
			return false;
		if (description == null) {
			if (other.description != null)
				return false;
		} else if (!description.equals(other.description))
			return false;
		if (editDate == null) {
			if (other.editDate != null)
				return false;
		} else if (!editDate.equals(other.editDate))
			return false;
		if (forceFormat == null) {
			if (other.forceFormat != null)
				return false;
		} else if (!forceFormat.equals(other.forceFormat))
			return false;
		if (hits == null) {
			if (other.hits != null)
				return false;
		} else if (!hits.equals(other.hits))
			return false;
		if (image == null) {
			if (other.image != null)
				return false;
		} else if (!image.equals(other.image))
			return false;
		if (keywords == null) {
			if (other.keywords != null)
				return false;
		} else if (!keywords.equals(other.keywords))
			return false;
		if (link == null) {
			if (other.link != null)
				return false;
		} else if (!link.equals(other.link))
			return false;
		if (publisher == null) {
			if (other.publisher != null)
				return false;
		} else if (!publisher.equals(other.publisher))
			return false;
		if (stat == null) {
			if (other.stat != null)
				return false;
		} else if (!stat.equals(other.stat))
			return false;
		if (title == null) {
			if (other.title != null)
				return false;
		} else if (!title.equals(other.title))
			return false;
		if (weight == null) {
			if (other.weight != null)
				return false;
		} else if (!weight.equals(other.weight))
			return false;
		if (weightDate == null) {
			if (other.weightDate != null)
				return false;
		} else if (!weightDate.equals(other.weightDate))
			return false;
		return true;
	}
	
	@PostLoad
	private void postLoad() {
		this.setHighLightTitle(this.getTitle());
		String content = this.getArticleData() ==null ? "" : this.getArticleData().getContent();
		if(org.apache.commons.lang3.StringUtils.isNoneBlank(content))this.setHighLightContent(StringUtils.replaceHtml(content));
	}

	@Override
	public void setHighLightContent(String content) {
		if (content == null)
			super.setHighLightContent(StringUtils.replaceHtml(this.getArticleData().getContent()));
		else
			super.setHighLightContent(content);
	}
}
